import datetime
import logging

from odoo import api, models, fields, _
from odoo.exceptions import ValidationError, UserError

_logger = logging.getLogger(__name__)


class StockMoveLine(models.Model):
    _inherit = 'stock.move.line'

    s_department_id = fields.Many2one('hr.department', string='Department', related='picking_id.apply_department_id')

    @api.model_create_multi
    def create(self, vals_list):
        for vals in vals_list:
            lot_id = vals.get('lot_id', False)
            if lot_id:
                lot_id = self.env['stock.lot'].search([('id', '=', lot_id)])
                if lot_id.is_lock and not self.env.context.get('is_stock_taking', False):
                    raise ValidationError(_('Lot: %s locked') % lot_id.name)
        return super(StockMoveLine, self).create(vals_list)

    def action_revert_inventory(self):
        if not self.env.user.has_group('base.group_system'):
            raise UserError(_("You don't have permission to perform this operation!"))

        return super().action_revert_inventory()

    @api.depends('product_id', 'picking_type_use_create_lots', 'lot_id.expiration_date', 'move_id.production_date')
    def _compute_expiration_date(self):
        for move_line in self:
            if not move_line.expiration_date and move_line.lot_id.expiration_date:
                move_line.expiration_date = move_line.lot_id.expiration_date
            elif move_line.picking_type_use_create_lots:
                if move_line.product_id.use_expiration_date:
                    if not move_line.expiration_date and move_line.move_id.production_date:
                        move_line.expiration_date = move_line.move_id.production_date + datetime.timedelta(
                            days=move_line.product_id.expiration_time)
                else:
                    move_line.expiration_date = False

    @api.onchange('product_id', 'product_uom_id')
    def _onchange_product_id(self):
        res = super()._onchange_product_id()
        if self.picking_type_use_create_lots:
            if self.product_id.use_expiration_date and self.move_id.production_date:
                self.expiration_date = self.move_id.production_date + datetime.timedelta(
                    days=self.product_id.expiration_time)
            else:
                self.expiration_date = False
        return res

    @api.model
    def is_division_integer(self, dividend, divisor, precision=4):
        if divisor == 0:
            return False

        factor = 10 ** precision
        int_dividend = int(round(dividend * factor))
        int_divisor = int(round(divisor * factor))
        return int_divisor != 0 and int_dividend % int_divisor == 0

    @api.constrains('state')
    def check_state_inherit(self):
        """
        完成时验证库位是否锁定,必须是未锁定的位置才可执行完成(原位置和目的位置)
        完成时检验调拨数量，必须是采购单位的整数倍
        """
        for move in self:
            location_is_lock = move.location_id.is_lock
            if location_is_lock:
                raise ValidationError(_('The transfer location is locked and verification cannot be performed'))
            location_dest_is_lock = move.location_dest_id.is_lock
            if location_dest_is_lock:
                raise ValidationError(_('The transfer destination is locked and verification cannot be performed!'))
        if not self.env['ir.config_parameter'].sudo().get_param('sb_stock_inherit.s_transfer_quantity_verification'):
            return
        for rec in self:
            if rec.state != 'done':
                continue
            if rec.location_id.usage == 'production' or rec.location_dest_id.usage == 'production':
                continue
            # 库存单位和采购单位相同，不限制
            if rec.product_id.uom_id == rec.product_id.uom_po_id:
                continue

            # uom_po_qty = rec.product_uom_id._compute_quantity(rec.quantity, rec.product_id.uom_po_id, round=False)
            one_po_qty = rec.product_id.uom_po_id._compute_quantity(1, rec.product_uom_id)
            if not self.is_division_integer(rec.quantity, one_po_qty):
                raise ValidationError(
                    _('Product: %s , The transfer quantity is not an integer multiple of the purchasing unit!',
                      rec.product_id.name))

    @api.onchange('lot_name')
    @api.constrains('lot_name')
    def _onchange_lot_name(self):
        for record in self:
            if not record.lot_name:
                continue
            # 仅校验 采购单 出入库批次
            # 校验批次, 如果批次单号已存在, 则判断该批次是否与本采购单相同, 不同则不允许使用该批次
            move_id = record.move_id
            purchase_line = move_id.purchase_line_id
            if not purchase_line:
                continue
            lot_ids = self.env['stock.lot'].sudo().search(
                [('name', '=', record.lot_name), ('product_id', '=', record.product_id.id)])
            if not lot_ids:
                continue
            # 存在批次单号, 需要判断批次单号是否与当前采购单相同
            old_purchase = lot_ids.purchase_order_ids
            if not old_purchase:
                continue
            if len(old_purchase) > 1:
                raise ValidationError(_('The lot number already exists, please do not use the same lot number!'))
            if purchase_line.order_id.id != old_purchase.id:
                raise ValidationError(_('The lot number already exists, please do not use the same lot number!'))
            if purchase_line.order_id.id not in old_purchase.ids:
                raise ValidationError(_('The lot number already exists, please do not use the same lot number!'))
